Angular Reactive Forms

In this tutorial, lets see how to use ReactiveForms in Angular to create a form to get use input and validate the form.

The terms that are used in Reactive forms are listed below.

  • FormControl
  • FormGroup
  • FormArray
  • FormBuilder
  • Validators

FormControl

FormControl is used to track the value and validation status of the individual form control.

FormGroup

FormGroup is used to track the value and status for the collection of form controls.

FormArray

FormArray is used to track the value and status for the array of form controls.

FormBuilder

FormBuilder provides to create instances of a FormControl, FormGroup, or FormArray. It reduces the amount of boilerplate needed to build complex forms.

Validators

The Validators are used to apply validations to the form controls.

Create an angular application

First, lets create an application using angular cli command.

ng new reactive-forms-tutorial

This will create a brand new angular application.

Add ReactiveFormsModule to to application

Next open the app.module.ts file and import the ReactiveFormsModule from @angular/forms and add it to the imports array of @NgModule decorator.

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { ReactiveFormsModule } from "@angular/forms";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, ReactiveFormsModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

Without importing ReactiveFormsModule we cannot use the Reactive forms in our application.

Create EmployeeComponent to setup ReactiveForm

Create a new component EmployeeComponent with the following command.

ng g c employee

This will create an angular component in employee folder. Now open the employee.component.ts file and modify the code as below.

import { Component, OnInit } from "@angular/core";
import {
  FormGroup,
  FormBuilder,
  FormControl,
  FormArray,
  Validators
} from "@angular/forms";
@Component({
  selector: "app-employee",
  templateUrl: "./employee.component.html",
  styleUrls: ["./employee.component.css"]
})
export class EmployeeComponent implements OnInit {
  employeeForm: FormGroup;
  constructor(private formBuilder: FormBuilder) {}

  ngOnInit() {
    this.employeeForm = this.formBuilder.group({
      employeeName: ["", Validators.required],
      designation: ["", Validators.required],
      gender: ["--Select--", Validators.required],
      address: ["", Validators.required],
      skills: this.formBuilder.array([new FormControl("", Validators.required)])
    });
  }

  addSkills() {
    const items = this.employeeForm.get("skills") as FormArray;
    items.push(new FormControl("", Validators.required));
  }

  onSubmit() {
    if (this.employeeForm.valid) {
      alert("Form submitted successfully.");
    }
  }
}

In the above code we have imported FormGroup, FormBuilder, FormControl, FormArray and Validators from @angular/forms inorder to use reactive forms.

Next, inject the FormBuilder to the constructor with a private variable named formBuilder. This is used to create FormGroup or FormArray in an easy way. We need to create a FormGroup to hold, group of FormControl's to get the employee details. Lets name the variable with the name employeeForm.

Next, in the ngOnInit() life cycle we shall create a FormGroup using FormBuilder object. The FormGroup will contain FormControl's like employeeName, designation, gender and address and a FormArray with the name skills.

We can add any number of skills to an employee, so that's why we have declare it as FormArray with initially one FormControl. In the sense,by default it will add one skill.

The addSkills() function is used to add a FormControl to the skills FormArray.

The onSubmit() function will open an alert box if the employeeForm is free of validation error.

Setting validation to FormContol

The validation is applied to the FormControl by means of Validators class.

Example, the FormControl for employeeName is represented as

["", Validators.required]

The "" represents the default value to the FormControl and Validators.required represents the required validator assigned to the FormControl.

Setting the html template of EmployeeComponent for ReactiveForm

Now looking to the employee.component.html file.

<div class="container">
  <form [formGroup]="employeeForm">
    <div class="form-group">
      <label for="employeeName">Employee Name</label>
      <input type="text" class="form-control" placeholder="Employee Name" formControlName="employeeName" />
      <span *ngIf="
          !employeeForm.get('employeeName').valid &&
          employeeForm.get('employeeName').touched &&
          employeeForm.get('employeeName').errors.required
        ">
        Name is required!
      </span>
    </div>
    <div class="form-group">
      <label for="designation">Designation</label>
      <input type="text" class="form-control" placeholder="Designation" formControlName="designation" />
      <span *ngIf="
          !employeeForm.get('designation').valid &&
          employeeForm.get('designation').touched &&
          employeeForm.get('designation').errors.required
        ">
        Designation is required!
      </span>
    </div>
    <div class="form-group">
      <label for="gender">Gender</label>
      <select formControlName="gender" class="form-control">
        <option>--Select--</option>
        <option value="male">Male</option>
        <option value="female">Female</option>
      </select>
      <span *ngIf="
          !employeeForm.get('gender').valid &&
          employeeForm.get('gender').touched &&
          employeeForm.get('gender').errors.required
        ">
        Gender is required!
      </span>
    </div>
    <div class="form-group">
      <label for="address">Address</label>
      <input type="text" class="form-control" placeholder="Address" formControlName="address" />
      <span *ngIf="
          !employeeForm.get('address').valid &&
          employeeForm.get('address').touched &&
          employeeForm.get('address').errors.required
        ">
        Address is required!
      </span>
    </div>
    <div formArrayName="skills">
      <ng-container *ngFor="let skill of employeeForm.get('skills').controls; let i = index">
        <div class="form-group">
          <label for="skills">Skills {{ i + 1 }}</label>
          <input type="text" [formControlName]="i" class="form-control" />
          <span *ngIf="
              !employeeForm.get('skills')['controls'][i].valid &&
              employeeForm.get('skills')['controls'][i].touched &&
              employeeForm.get('skills')['controls'][i].errors.required">
            Skill is required!
          </span>
        </div>
      </ng-container>
    </div>
    <button type="submit" class="btn btn-primary" (click)="onSubmit()">
      Submit
    </button>
    <button class="btn btn-danger" (click)="addSkills()">Add Skill</button>
  </form>
</div>

In the employee.component.html file, we initially set the formGroup to employeeForm in form tag.

For each input controls, we give a name of the FormControl in formControlName.

The *ngIf directive is used to check for any validation error for the FormControl by checked whether the FormControl is valid or not and check whether it has been touched and whether required error is in errors object of the FormControl.

The skills is a FormArray, so we loop through the controls in the FormArray using ngFor directive and assign the index position of the FormControl as the name to formControlName.

Clicking on submit button will call the onSubmit() function, which in turns, checks whether the form is valid or not and displays an

Run the app using

ng serve --o

Output with validation error.

Output with success alert message.


Most Read